package com.sdses.weather.config.exception;

import cn.hutool.core.convert.Convert;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.sdses.weather.common.ApiResult;
import com.sdses.weather.common.error.ErrCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController;
import org.springframework.boot.web.servlet.error.DefaultErrorAttributes;
import org.springframework.context.support.DefaultMessageSourceResolvable;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.ObjectError;
import org.springframework.web.HttpMediaTypeException;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.NoHandlerFoundException;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;


/**
 * 全局异常处理: 捕获Controller异常
 */
@Slf4j
@RestControllerAdvice
public class GlobalException {

    @ExceptionHandler(value = Exception.class)
    @ResponseBody
    public Object errorHandler(HttpServletRequest request, Exception ex) throws IOException {
        String url = request.getServletPath();
        Map parameterMap = request.getParameterMap();
        String contentType = request.getContentType();
        String method = request.getMethod();

        String params = "";
        if (MapUtil.isNotEmpty(parameterMap)) {
            params = JSONUtil.toJsonStr(request.getParameterMap());
        } else {
            params = IoUtil.readUtf8(request.getInputStream()).replaceAll("\\s+", " ");
        }
        log.info("error method: {};\nurl: {};\ncontentType: {};\nparams: {}", method, url, contentType, params);

        String message = Convert.unicodeToStr(ex.getMessage());
        Throwable throwable = ex.getCause();
        if (message == null) {
            message = throwable != null ? throwable.toString() : message;
        }
        if (ex instanceof BusinessException) {
            BusinessException exception = (BusinessException) ex;
            return ApiResult.fail(exception.getCode() + "", exception.getMsg());

        }
        log.error("系统异常", ex);

        if (ex instanceof HttpMediaTypeException || ex instanceof NoHandlerFoundException) {

            //404错误
            return ApiResult.fail(ErrCode.PAGE_NOT_FOUND);
        } else if (ex instanceof ArithmeticException || ex instanceof IndexOutOfBoundsException || throwable instanceof ArithmeticException || throwable instanceof IndexOutOfBoundsException) {

            //系统错误
            return ApiResult.fail(ErrCode.FAILED);
        }
        //系统错误
        return StrUtil.isBlank(message) ? ApiResult.fail(ErrCode.FAILED) : ApiResult.fail(message);
    }
}


/**
 * 全局异常处理: 捕获Filter异常
 */
@Slf4j
@RestController
class WeatherErrorController extends BasicErrorController {

    public WeatherErrorController(ServerProperties serverProperties) {
        super(new DefaultErrorAttributes(), serverProperties.getError());
    }

    @Override
    @RequestMapping(produces = {MediaType.APPLICATION_JSON_VALUE})
    public ResponseEntity<Map<String, Object>> error(HttpServletRequest request) {
        Map<String, Object> body = getErrorAttributes(request, getErrorAttributeOptions(request, MediaType.ALL));
        HttpStatus status = getStatus(request);
        return new ResponseEntity(ApiResult.fail(ErrCode.FAILED.getCode(), JSONUtil.toJsonStr(body.get("message"))), status);
    }
}



